package com.wlb.address.split.process;

import com.wlb.address.split.dict.DATrieDict;
import com.wlb.address.split.domain.AddrLevel;
import com.wlb.address.split.domain.BuildingNo;
import com.wlb.address.split.domain.Constants;
import com.wlb.address.split.domain.GeoTerm;
import com.wlb.address.split.rule.ExperienceRuleSet;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 特殊词性的词的处理.
 * User: xiaotong.dxt
 * Date: 13-8-8
 * Time: 下午3:10
 * To change this template use File | Settings | File Templates.
 */
public class WordProcessor {


    private static DATrieDict dict = null;

    //F词性 办事处   77  调查队   77 分校   77
    //主要用于处理类似XXX学院XXX校区的情况，防止被错分为两个POI，为独占词性
    public static boolean FProp_Deal(FusionResultSet fusionResultSet, String strWordName, boolean bMerge) {
        if (fusionResultSet.size() == 0) {
            if (bMerge) {
                fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_POI, 2);
            } else {
                fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_ADDR_INFO, 2);
            }
            return true;
        }

        AddrLevel nLevel = fusionResultSet.peekLast().nLevel;
        //对于办事处处理
        if (strWordName.equals("办事处")) {
            if (nLevel.getLevel() < AddrLevel.AL_ROAD.getLevel() || nLevel == AddrLevel.AL_POI) {
                //如果前一个词是xxx街道，则和办事处连接起来作为街道办事处
                if (fusionResultSet.peekLast().strWordName.endsWith("街道")) {
                    fusionResultSet.peekLast().nLevel = AddrLevel.AL_TOWN;
                } else {
                    //如果是XXX办事处，则连接起来作为POI
                    fusionResultSet.peekLast().nLevel = AddrLevel.AL_POI;
                    fusionResultSet.peekLast().chProp = '1';
                }
                fusionResultSet.peekLast().strWordName += strWordName;
                fusionResultSet.peekLast().nProp = 2;
                fusionResultSet.peekLast().chProp = 'H';//将其设置为一个门面，保证以后不继续往下合并了
                return true;
            } else {
                fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_ADDR_INFO, 2);
                return true;
            }
        }

        ////////////////如果前一个term是开发区之类的//////////////////////////////////
        //如果前一个词是开发区,且不确定，是推理的，则合并起来作为POI，例如 德玛西亚开发区办事处。作为整个POI
        if (!bMerge && fusionResultSet.peekLast().nLevel == AddrLevel.AL_DEV_ZONE && fusionResultSet.peekLast().nProp == Constants.PROP_TYPE_THINK) {
            fusionResultSet.peekLast().strWordName += strWordName;
            fusionResultSet.peekLast().nLevel = AddrLevel.AL_POI;
            fusionResultSet.peekLast().chProp = '2';
            return true;
        }
        //如果前一个是商圈、道路、子路、POI，
        if (nLevel == AddrLevel.AL_BIZ_ZONE || nLevel == AddrLevel.AL_ROAD || nLevel == AddrLevel.AL_SUB_ROAD || nLevel == AddrLevel.AL_POI) {
            String strTemp = fusionResultSet.peekLast().strWordName;
            //因为此TERM通常为一个后缀，所以和前一个合并

            strTemp += strWordName;
            //如果元素个数为1
            if (fusionResultSet.size() == 1) {
                //如果唯一一个元素是POI,则合并
                if (fusionResultSet.peekLast().nLevel == AddrLevel.AL_POI) {

                    fusionResultSet.peekLast().strWordName += strWordName;
                    fusionResultSet.peekLast().nProp = Constants.PROP_TYPE_MATCH;
                    fusionResultSet.peekLast().chProp = '2';
                } else {
                    //否则将其作为POI
                    fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_ADDR_INFO, 2);
                    return true;
                }
            } else {
                //如果融合集长度大于1
                if (bMerge) {
                    //如果前一个是路\辅路
                    if (nLevel == AddrLevel.AL_ROAD || nLevel == AddrLevel.AL_SUB_ROAD) {
                        //如果倒数第二个为POI      ,说明是POI+路+77的形式
                        if (fusionResultSet.get(fusionResultSet.size() - 2).nLevel == AddrLevel.AL_POI) {
                            //江西省宜春市高安市建设银行筠泉路瑞州分理处(南街)
                            fusionResultSet.get(fusionResultSet.size() - 2).strWordName += strTemp;
                            fusionResultSet.get(fusionResultSet.size() - 2).nProp = Constants.PROP_TYPE_THINK;
                            fusionResultSet.get(fusionResultSet.size() - 2).chProp = '2';
                            //合并完后删除最后一个
                            fusionResultSet.popLast();
                        } else {
                            // 则直接作为POI
                            fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_POI, 2);
                            fusionResultSet.peekLast().chProp = '2';
                        }

                    } else {
                        fusionResultSet.peekLast().strWordName += strWordName;
                        fusionResultSet.peekLast().nProp = Constants.PROP_TYPE_THINK;
                        fusionResultSet.peekLast().chProp = '2';
                    }
                    return true;
                } else {
                    //如果不融合  TODO 这里有疑问
                    if (fusionResultSet.get(fusionResultSet.size() - 2).nLevel == AddrLevel.AL_POI) {
                        fusionResultSet.get(fusionResultSet.size() - 2).strWordName += strTemp;
                        fusionResultSet.get(fusionResultSet.size() - 2).nProp = Constants.PROP_TYPE_THINK;
                        fusionResultSet.get(fusionResultSet.size() - 2).chProp = '2';
                        //跟前一个融合后删除
                        fusionResultSet.popLast();
                    } else {
                        fusionResultSet.get(fusionResultSet.size() - 1).strWordName = strTemp;
                        fusionResultSet.get(fusionResultSet.size() - 1).nProp = Constants.PROP_TYPE_THINK;
                        fusionResultSet.get(fusionResultSet.size() - 1).nLevel = AddrLevel.AL_POI;
                        fusionResultSet.get(fusionResultSet.size() - 1).chProp = '2';
                    }
                    return true;

                }
            }
        } else {
            fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_POI, 2);
            fusionResultSet.get(fusionResultSet.size() - 1).chProp = '2';
            return true;
        }
        return false;

    }

    public static boolean AdminArea_SpecDistrict(FusionResultSet fusionResultSet, String strWordName) {
        if (fusionResultSet.size() > 0) {
            String lastWordName = fusionResultSet.peekLast().strWordName;
            AddrLevel nLevel = fusionResultSet.peekLast().nLevel;
            if (nLevel == AddrLevel.AL_CITY) {
                ////山西省大同市城区复地紫城B2-3-701
                if (strWordName.equals("城区")) {
                    //靠 这些城市居然管辖"城区"这样的区
                    //  汕尾市：城区
                    //	大同市：城区
                    //	阳泉市：城区
                    //	长治市：城区
                    //	晋城市：城区
                    if (ExperienceRuleSet.getInstance().cityWithChengquDistrict.contains(strWordName)) {
                        fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_DISTRICT, 1);
                        return true;
                    }

                } else if (strWordName.equals("矿区")) {
                    //带矿区的地址
                    //	大同市：矿区
                    //	阳泉市：矿区
                    if (ExperienceRuleSet.getInstance().cityWithKuangquDistrict.contains(strWordName)) {
                        fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_DISTRICT, 1);
                        return true;
                    }
                } else if (strWordName.equals("郊区")) {
                    //	阳泉市：郊区
                    //	长治市：郊区
                    if (ExperienceRuleSet.getInstance().cityWithJiaoquDistrict.contains(strWordName)) {
                        fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_DISTRICT, 1);
                        return true;
                    }
                } else if (strWordName.equals("东区") || strWordName.equals("西区")) {
                    if (ExperienceRuleSet.getInstance().cityWithDongquXiquDistrict.contains(strWordName)) {
                        fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_DISTRICT, 1);
                        return true;
                    }
                }
            }

        }
        return false;
    }

    //J是开发区 街道 村 之类的
    public static boolean JPro_Deal(FusionResultSet fusionResultSet, String strWordName) {
        if (fusionResultSet.peekLast().strWordProp.contains("J")) {
            if (fusionResultSet.size() == 0) {
                fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_DEV_ZONE, 2);
                return true;
            }
            AddrLevel nLevel = fusionResultSet.peekLast().nLevel;
            //如果前一个是不小于商圈或者POI的term 则向前合并
            if (fusionResultSet.size() > 0 && (nLevel.getLevel() <= AddrLevel.AL_BIZ_ZONE.getLevel() || nLevel == AddrLevel.AL_POI)) {
                fusionResultSet.peekLast().strWordName += strWordName;
                fusionResultSet.peekLast().nLevel = AddrLevel.AL_DEV_ZONE;
                fusionResultSet.peekLast().nProp = Constants.PROP_TYPE_THINK;
            } else {
                fusionResultSet.insertWordtoResultSet(strWordName, AddrLevel.AL_DEV_ZONE, 2);
            }
        }
        return false;
    }

    /**
     * 社区/村后缀的判定
     *
     * @return 是否处理成功
     */

    public static boolean Village_Community(String strWordName, FusionResult fusionResult) {
        //如果当前词是街道
        if (ExperienceRuleSet.getInstance().townSuffixSet.contains(strWordName)) {
            fusionResult.strWordName += strWordName;
            fusionResult.nLevel = AddrLevel.AL_TOWN;
            fusionResult.nProp = Constants.PROP_TYPE_THINK;
            return true;

        } else if (ExperienceRuleSet.getInstance().townSuffixSet.contains(strWordName)) {
            //如果当前词是社区或者村
            fusionResult.strWordName += strWordName;
            fusionResult.nLevel = AddrLevel.AL_VILLAGE;
            fusionResult.nProp = Constants.PROP_TYPE_THINK;
            return true;
        }
        return false;
    }

    public static boolean singleWordDeal(int i, String wordName, FusionResultSet fusionResultSet, List<GeoTerm> termOut) {

        //如何是最后一个元素
        if (i + 1 == termOut.size()) {
            //这个数字判断不是很清楚是什么意思 TODO
            if (termOut.get(i).getNo_type().getIntType() >= BuildingNo.NO_ArabicDigit.getIntType() && termOut.get(i).getNo_type().getIntType() < BuildingNo.NO_AllChn.getIntType()) {
                fusionResultSet.insertWordtoResultSet(wordName, AddrLevel.AL_ADDR_INFO, 2);
                return true;
            }
        }
        boolean bFaild = StringUtils.isNumeric(wordName);//是否是全数字
        if (!bFaild) {
            //如果不是全数字
            if (wordName.equals("办")) {
                if (fusionResultSet.size() > 0) {
                    if ((fusionResultSet.peekLast().nLevel == AddrLevel.AL_TOWN || fusionResultSet.peekLast().nLevel == AddrLevel.AL_POI) && fusionResultSet.peekLast().strWordName.endsWith("街道")) {
                        fusionResultSet.peekLast().strWordName += wordName;
                        fusionResultSet.peekLast().nLevel = AddrLevel.AL_TOWN;
                        fusionResultSet.peekLast().nProp = 2;
                        return true;
                    }
                }
            }

            String strWordProp = termOut.get(i).getProp();

            //TODO 这里的融合逻辑还是不是很清楚
            if (!strWordProp.equals("Z") && strWordProp.equals("G")) {
                if (strWordProp.equals("$")) {
                    //如果是两个字以上的前缀 则返回false 不融合
                    if (wordName.length() > 1 || wordName.length() < 1) {
                        return false;
                    }
                }
            }

        }

        bFaild = false;
        //这里还是未知属性的词的处理
        bFaild = UnknownPropWordDeal(i, wordName, fusionResultSet, termOut);
        return false;
    }

    public static boolean UnknownPropWordDeal(int i, String wordName, FusionResultSet fusionResultSet, List<GeoTerm> termOut) {
        boolean bFaild = false;
        int nPregit = i;
        String strTemp1 = "";
        //从当前位置开始遍历剩下的字
        while (i < termOut.size()) {
            String strTempProp = termOut.get(i).getProp();


            //H属性的单字
            if (strTempProp.contains("H") && termOut.get(i).getWord().length() == 1) {
                char chState = 0;
                if (SpecConectWordDeal(wordName, chState, termOut, i, fusionResultSet)) {
                     // 说明后面又文字可以和这个词连接
                    int nTempSize = strTemp1.length();

                    //这里很含糊需要确定了再写       TODO

                }
            }
            //对于H属性的判定      TODO

            //如果当前属性是$ 表示是前缀
            if (strTempProp.equals("$")) {
                strTemp1 += termOut.get(i).getWord();
                i++;
                continue;

            } else {
                // 主要用于处理类似XXX学院XXX校区的情况，防止被错分为两个POI，为独占词性
                if (termOut.get(i).getProp().equals("F")) {
                    boolean bMergeWord = true;
                    if (strTemp1.isEmpty())
                        bMergeWord = false;
                    //TODO 这里有点不清楚
                    if (strTemp1.length() > 1 && IsGPropInclude(nPregit, i - 1, termOut)) {
                        fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_ADDR_INFO, 2);
                        i--;
                        return true;
                    }
                    strTemp1 += termOut.get(i).getWord();
                    FProp_Deal(fusionResultSet, strTemp1, bMergeWord);
                    return true;

                }
                //对J属性的单字进行处理
                if (termOut.get(i).getProp().equals("J")) {


/*
                    if ( strTemp1.size() > 1 &&
                            Is_GProp_Include( nPregit,git-1,GeoTermout ) )
                    {/////G属性处理////
                        InsertWordtoResultSet(FusionResultSet,AddrLevelExist,
                                strTemp1,AL_ADDR_INFO,2);
                        git--;////
                        return true;
                    }
*/
                    bFaild = WordProcessor.DEV_ZONE_DEAL(termOut, i, wordName, fusionResultSet);
                    if (bFaild)
                        return true;

                }
                //对R属性做处理
                if (termOut.get(i).getProp().contains("R")) {
                    /*
                    if ( strTemp1.size() > 1 &&
                            Is_GProp_Include( nPregit,git-1,GeoTermout ) )
                    {/////G属性处理////
                        InsertWordtoResultSet(FusionResultSet,AddrLevelExist,
                                strTemp1,AL_ADDR_INFO,2);
                        git--;////
                        return true;
                    }
*/
                    //如果当前词为道路
                    if (ExperienceRuleSet.IsRoad(termOut.get(i).getWord())) {
                        strTemp1 += termOut.get(i).getWord();
                        fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_ROAD, 2);
                        return true;//合并为路
                    }

                }
                // 如果没有任何结果 则将strTemp和当前term合并
                strTemp1 += termOut.get(i).getWord();
            }
            //特殊单字，处理支路的情况
            bFaild = WordProcessor.Pre_SingleChnCharacters(strTemp1, fusionResultSet);
            //遇到街道的情况继续往前合并
            if (bFaild) {
                //下一个有字
                if (i + 1 < termOut.size()) {
                    if (termOut.get(i + 1).getWord().equals("道")) {
                        if (fusionResultSet.size() > 0) {
                            fusionResultSet.peekLast().strWordName += "道";
                            fusionResultSet.peekLast().nLevel = AddrLevel.AL_TOWN;
                            fusionResultSet.peekLast().nProp = Constants.PROP_TYPE_THINK;
                            i++;
                            return true;
                        }

                    }
                }
                return true;
            }
            bFaild = AdminArea_Community_Street_Decide(termOut, i, strTemp1);
            if (bFaild) {
                return true;
            }
            //如果单字拼装成道路 则看是否是主路、附路
            if (ExperienceRuleSet.IsRoad(strTemp1)) {
                if (!fusionResultSet.hasLevel(AddrLevel.AL_ROAD)) {
                    fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_ROAD, 2);
                    return true;
                } else if (!fusionResultSet.hasLevel(AddrLevel.AL_SUB_ROAD)) {
                    fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_SUB_ROAD, 2);
                    return true;
                } else {
                    fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_ROAD, 2);
                    return true;
                }
            }

            //判断拼装出来的是不是社区
            if (ExperienceRuleSet.IsCommunity(strTemp1)) {
                if (!fusionResultSet.hasLevel(AddrLevel.AL_VILLAGE)) {
                    if (!fusionResultSet.hasLevel(AddrLevel.AL_ROAD) && !fusionResultSet.hasLevel(AddrLevel.AL_SUB_ROAD) && !fusionResultSet.hasLevel(AddrLevel.AL_POI)) {
                        fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_VILLAGE, 2);
                        fusionResultSet.lastLevel = AddrLevel.AL_VILLAGE;
                        return true;
                    } else {
                        fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_POI, 2);
                        fusionResultSet.lastLevel = AddrLevel.AL_POI;
                        return true;
                    }

                }
            }
            //对于后缀次的处理
            if (termOut.get(i).getProp().equals("A")) {
                if (fusionResultSet.size() > 0) {
                    //如果允许
                    if (IsAllowed_ResultSetMerge(fusionResultSet)) {

                    }
                }

            }


        }   //循环结束
        //对于直到结束也无法认证的词语
        if (i == termOut.size()) {
            i--;
            //如果中间没有连接词 则认为是个完整的POI
            if (IsGPropInclude(nPregit, i, termOut)) {
                fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_ADDR_INFO, 2);
                return true;

            }

            /////这里需要判定///
            ///1.全部为数字的时候，当 AL_ADDR_INFO
            ///2.如果结束词条中带有后缀词的则当成POI////
            if (StringUtils.isNumeric(strTemp1) || digit_Meter(strTemp1)) {
                fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_ADDR_INFO, 2);
                return true;
            } else if (Words_Include_suffix(fusionResultSet, strTemp1)) {
                return true;
            }
            fusionResultSet.insertWordtoResultSet(strTemp1, AddrLevel.AL_ADDR_INFO, 2);
            return true;

        }
        return false;
    }

    //看一个字符串是否带有POI的后缀
    private static boolean Words_Include_suffix(FusionResultSet fusionResultSet, String wordName) {
        List<GeoTerm> terms = new ArrayList<GeoTerm>();
        //文字大于3的才去匹配
        if (StringUtils.isNotBlank(wordName) && wordName.length() > 3) {
            String suffix = wordName;
            if (wordName.length() >= 6) {
                suffix = suffix.substring(suffix.length() - 6);
            }
            dict.split(suffix, terms);
            if (terms.size() > 0) {
                String lastProp = terms.get(terms.size() - 1).getProp();
                if (lastProp.equals("A") || lastProp.equals("B") || lastProp.contains("P") || lastProp.contains("E")) {
                    fusionResultSet.insertWordtoResultSet(wordName, AddrLevel.AL_POI, 2);

                    return true;
                } else if (lastProp.equals("F")) {
                    FProp_Deal(fusionResultSet, wordName, false);
                    return true;
                } else if (lastProp.equals("J")) {
                    fusionResultSet.insertWordtoResultSet(wordName, AddrLevel.AL_DEV_ZONE, 2);
                    return true;
                }
            }

        }

        return false;
    }

    //对数字+千米的处理
    private static boolean digit_Meter(String str) {
        return false;
    }

    private static boolean Pre_SingleChnCharacters(String strWordName, FusionResultSet fusionResultSet) {
        //如果当前不是单子 则跳过
        if (strWordName.length() != 1)
            return false;
        if (fusionResultSet.size() > 0) {

            //G和H的单字不处理      描述性
            if (fusionResultSet.peekLast().chProp == 'G' || fusionResultSet.peekLast().chProp == 'H') {
                return false;
            }
            if (ExperienceRuleSet.IsRoadSuffix(strWordName)) {
                //这个表示是支路的情况
                if (strWordName.equals("弄") || strWordName.equals("巷")) {
                    fusionResultSet.peekLast().strWordName += strWordName;
                    fusionResultSet.peekLast().nLevel = AddrLevel.AL_SUB_ROAD;
                    fusionResultSet.peekLast().nProp = Constants.PROP_TYPE_THINK;
                    return true;
                } else {
                    fusionResultSet.peekLast().strWordName += strWordName;
                    fusionResultSet.peekLast().nLevel = AddrLevel.AL_ROAD;
                    fusionResultSet.peekLast().nProp = Constants.PROP_TYPE_THINK;
                    return true;

                }
            }
        }
        return false;
    }

    //
    private static boolean AdminArea_Community_Street_Decide(List<GeoTerm> terms, int i, String strTemp) {
        //TODO
        if (strTemp.length() == 1)
            return false;
        return true;
    }

    //判断后续合并的属性之中是否含有G属性词条
    private static boolean IsGPropInclude(int nStartPos, int nEndPos, List<GeoTerm> termOut) {

        if (nStartPos < 0)
            nStartPos = 0;
        if (nEndPos > (termOut.size() - 1))
            nEndPos = termOut.size() - 1;
        for (int i = nStartPos; i <= nEndPos; i++) {
            if (termOut.get(i).getProp().equals("G"))
                return true;
        }
        return false;
    }

    //对 和，与等滕姝关键词的处理
    public static boolean SpecConectWordDeal(String strWordName, char chState, List<GeoTerm> termOut, int i, FusionResultSet fusionResultSet) {

        //如果不是一个字
        if (strWordName.length() != 1) {
            return false;
        }
        if (strWordName.equals("和") || strWordName.equals("与")) {
            int termOutSize = termOut.size();
            int fusionSize = fusionResultSet.size();
            chState = 1;
            //如果当前term不是最后一个term且下一个term为POI或者M
            if ((i + 1) < termOutSize && (termOut.get(i + 1).getProp().contains("P") || termOut.get(i + 1).getProp().contains("M"))) {
                return true;
            }
            //从下个词开始
            for (int ngt = i + 1; ngt < termOutSize; ngt++) {
                //如果前一个词词性本来就是道路
                if (termOut.get(ngt).getProp().contains("R")) {
                    chState = 2;
                    break;
                } else if (ExperienceRuleSet.IsRoad(strWordName)) {
                    chState = 2;
                    break;
                } else if (termOut.get(ngt).getProp().contains("H")) {
                    //下一词
                    //如果是H词性的词
                    String strTemp = termOut.get(ngt).getProp();
                    //交叉口判断
                    if (strTemp.contains(strTemp)) {
                        chState = 2;
                        break;
                    }
                    break;
                }
            }
            if (chState == 2)
                return true;
            else {
                //无法跟后面的词形成配对。所以认为是无效字
                termOut.get(i).setProp("Z");
            }
        }

        return false;
    }


    //通过词性判断决定开发区是否要合并
    private static boolean DEV_ZONE_DEAL(List<GeoTerm> termOut, int i, String wordName, FusionResultSet fusionResultSet) {
        return false;
    }

    private static boolean IsAllowed_ResultSetMerge(FusionResultSet fusionResultSet) {
        if (fusionResultSet.size() > 0) {
            if (fusionResultSet.peekLast().chProp == 'G' || fusionResultSet.peekLast().chProp == 'H' || fusionResultSet.peekLast().chProp == '2') {
                return true;
            }
        }
        return false;
    }


}


